package com.zhouw.graphiclibrary;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.icu.util.Calendar;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationSet;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;

/**
 * 银川鸿联科技有限公司
 * 作者 周伟 on 2018-06-08.
 * 邮箱 1300012858@qq.com
 */

public class StatusIcon extends View {
    //中心X，Y坐标
    int centerX = 0;
    int centerY = 0;
    //环形半径 与画笔宽度
    float ringRadius = 50;
    float outRingWidth = 1;
    //圆面半径
    float circleRadius = 50;
    //中心图案颜色
    int centerIconClor = Color.WHITE;
    //环，圆面背景，圆面缩小效果的颜色
    int ringColor, backgroundCirclrColor, zoomInCircleColor;
    //最外侧缩放圆环的倍数（整数）
    int outRingScale;
    //圆环的动画时间
    int ringDuration;
    //圆面的动画时间
    int zoomInDuration;
    //最外层缩放圆环的动画时间
    int outScaleDuration;
    //view类型 1 正确 2 错误
    int status = 1;
    Paint ringPaint, circlePaint, rightPaint, bgCirclePaint, outRingPaint;
    RectF rectF, outRecfF;
    Path path, rightPath, wrongPath;
    //圆环动画的进度
    float currentProcess = 0;
    AnimatorSet set;
    boolean clearCanvas = false;
    public StatusIcon(Context context) {
        this(context, null);
    }

    public StatusIcon(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.StatusIcon);
        circleRadius = dp2px(context, ta.getDimension(R.styleable.StatusIcon_radius, 30));
        outRingWidth = dp2px(context, ta.getDimension(R.styleable.StatusIcon_scaleWidth, 2));
        outRingScale = ta.getInt(R.styleable.StatusIcon_outRingScale, 10);
        ringRadius = circleRadius;
        ringDuration = ta.getInt(R.styleable.StatusIcon_ringDuration, 700);
        zoomInDuration = ta.getInt(R.styleable.StatusIcon_zoomInDuration, 500);
        outScaleDuration = ta.getInt(R.styleable.StatusIcon_outScaleDuration, 500);
        status = ta.getInt(R.styleable.StatusIcon_status, 1);
        switch (status) {
            case 1:
                ringColor = ta.getColor(R.styleable.StatusIcon_ringColor, Color.YELLOW);
                backgroundCirclrColor = ta.getColor(R.styleable.StatusIcon_backgroundCirclrColor, Color.YELLOW);
                zoomInCircleColor = ta.getColor(R.styleable.StatusIcon_zoomInCircleColor, Color.WHITE);
                centerIconClor = ta.getColor(R.styleable.StatusIcon_rightColor, Color.WHITE);
                break;
            case 2:
                ringColor = ta.getColor(R.styleable.StatusIcon_wrongRingColor, Color.RED);
                backgroundCirclrColor = ta.getColor(R.styleable.StatusIcon_wrongbackgroundCirclrColor, Color.RED);
                zoomInCircleColor = ta.getColor(R.styleable.StatusIcon_wrongZoomInCircleColor, Color.WHITE);
                centerIconClor = ta.getColor(R.styleable.StatusIcon_wrongColor, Color.WHITE);
                break;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
        init();
    }

    private int measureHeight(int measureSpec) {
        int result = 50;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = Math.min((int) (2 * ringRadius + outRingScale * outRingWidth) + getPaddingTop() + getPaddingBottom(), size);
        }
        return result;
    }

    private int measureWidth(int measureSpec) {
        int result = 50;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = Math.min((int) (2 * ringRadius + outRingScale * outRingWidth) + getPaddingLeft() + getPaddingRight(), size);
        }
        return result;
    }

    private void init() {
       initCenterPoint();
        initPaint();
        initPath();
        initAnimator();
    }

    private void initCenterPoint(){
        centerX = getMeasuredWidth() / 2;
        centerY = getMeasuredHeight() / 2;
        centerY = Math.min(centerX, centerY);
    }
    private void initPaint(){
        ringPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        ringPaint.setAntiAlias(true);
        ringPaint.setColor(ringColor);
        ringPaint.setStrokeWidth(10);
        ringPaint.setStyle(Paint.Style.STROKE);
        rectF = new RectF(centerX - ringRadius, centerY - ringRadius, centerX + ringRadius, centerY + ringRadius);
        circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        circlePaint.setColor(zoomInCircleColor);
        circlePaint.setAntiAlias(true);
        bgCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bgCirclePaint.setColor(backgroundCirclrColor);
        bgCirclePaint.setAntiAlias(true);
        outRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        outRingPaint.setColor(ringColor);
        outRingPaint.setAntiAlias(true);
        outRingPaint.setStyle(Paint.Style.STROKE);
        rightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        rightPaint.setColor(centerIconClor);
        rightPaint.setAntiAlias(true);
        rightPaint.setStrokeWidth(10);
        rightPaint.setStyle(Paint.Style.STROKE);
    }
    private void initPath(){
        rightPath = new Path();
        float rightPoint[][] = {{centerX - (float) (0.4 * ringRadius), centerY}, {centerX, (float) (4 / 15.0 * ringRadius) + centerY}, {(float) (0.4 * ringRadius) + centerX, centerY - (float) (0.3 * ringRadius)}};
        rightPath.moveTo(rightPoint[0][0], rightPoint[0][1]);
        rightPath.lineTo(rightPoint[1][0], rightPoint[1][1]);
        rightPath.lineTo(rightPoint[2][0], rightPoint[2][1]);
        wrongPath = new Path();
        float wrongPoint[][] = {{centerX - (float) (0.3 * ringRadius), centerY - (float) (0.3 * ringRadius)}, {centerX + (float) (0.3 * ringRadius), centerY + (float) (0.3 * ringRadius)}, {centerX - (float) (0.3 * ringRadius), centerY + (float) (0.3 * ringRadius)}, {centerX + (float) (0.3 * ringRadius), centerY - (float) (0.3 * ringRadius)}};
        wrongPath.moveTo(wrongPoint[0][0], wrongPoint[0][1]);
        wrongPath.lineTo(wrongPoint[1][0], wrongPoint[1][1]);
        wrongPath.moveTo(wrongPoint[2][0], wrongPoint[2][1]);
        wrongPath.lineTo(wrongPoint[3][0], wrongPoint[3][1]);
        Path[] paths = new Path[]{rightPath, wrongPath};
        path = new Path(paths[status - 1]);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(clearCanvas){
            Paint paint = new Paint();
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            canvas.drawPaint(paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
            clearCanvas = false;
        }
        canvas.drawArc(rectF, 0, currentProcess, false, ringPaint);
        if (currentProcess >= 360f) {
            canvas.drawCircle(centerX, centerY, ringRadius, bgCirclePaint);
            canvas.drawCircle(centerX, centerY, circleRadius, circlePaint);
        }
        if (circleRadius <= 0) {
            canvas.drawPath(path, rightPaint);
            outRecfF = new RectF(centerX - ringRadius, centerY - ringRadius, centerX + ringRadius, centerY + ringRadius);
            outRingPaint.setStrokeWidth(outRingWidth);
            canvas.drawArc(outRecfF, 0, 360, false, outRingPaint);
        }
    }

    private void initAnimator() {
        final ValueAnimator zoomOutInAnimator = ValueAnimator.ofFloat(outRingWidth, outRingScale * outRingWidth, outRingWidth).setDuration(outScaleDuration);
        zoomOutInAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        zoomOutInAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                outRingWidth = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        final ValueAnimator zoomInAnimator = ValueAnimator.ofFloat(circleRadius, 0).setDuration(zoomInDuration);
        zoomInAnimator.setInterpolator(new LinearInterpolator());
        zoomInAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                circleRadius = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        ValueAnimator ringAnimator = ValueAnimator.ofFloat(0, 360f).setDuration(ringDuration);
        ringAnimator.setInterpolator(new AccelerateInterpolator());
        ringAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentProcess = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        ringAnimator.start();

        set = new AnimatorSet();
        set.play(ringAnimator).before(zoomInAnimator);
        set.play(zoomInAnimator).before(zoomOutInAnimator);
        set.start();
    }

    private float dp2px(Context context, float inputValue) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, inputValue, context.getResources().getDisplayMetrics());
    }

    public void setStatus(StatusEnum status) {
        this.status = status.ordinal()+1;
        invalidate();
    }

    public enum StatusEnum{
        Right,
        Wrong;
    }
}
